import { Defect, AggregatedDefect, DefectGroup, DefectDetails, ProcessedData } from "./types";

// 验证函数
function validateDefect(item: Defect): void {
  if (item.area < 0 || item.longSide < 0 || item.shortSide < 0) {
    throw new Error(`Invalid dimensions for defect at (${item.x}, ${item.y})`);
  }
  if (item.score < 0 || item.score > 1) {
    throw new Error(`Invalid score for defect at (${item.x}, ${item.y})`);
  }
  if (item.x < 0 || item.y < 0) {
    throw new Error(`Invalid coordinates for defect at (${item.x}, ${item.y})`);
  }
  if (typeof item.type !== 'string' || item.type.trim() === '') {
    throw new Error(`Invalid type for defect at (${item.x}, ${item.y})`);
  }
}

// 统计配置
const statsConfig: {
  [key: string]: (item: Defect, current: number) => number;
} = {
  totalArea: (item: Defect, current: number) => current + item.area,
  maxLongSide: (item: Defect, current: number) => Math.max(current, item.longSide),
  minLongSide: (item: Defect, current: number) => Math.min(current, item.longSide),
  maxShortSide: (item: Defect, current: number) => Math.max(current, item.shortSide),
  minShortSide: (item: Defect, current: number) => Math.min(current, item.shortSide),
  maxArea: (item: Defect, current: number) => Math.max(current, item.area),
  minArea: (item: Defect, current: number) => Math.min(current, item.area),
};

// 预处理函数
export function preprocess(defectList: Defect[], includeStats: boolean = false): ProcessedData {
  const grouped = new Map<string, AggregatedDefect>();

  defectList.forEach(item => {
    // 验证输入
    validateDefect(item);

    const coordKey = `${item.x},${item.y}`;
    let group = grouped.get(coordKey);
    if (!group) {
      group = { 
        x: item.x, 
        y: item.y, 
        flaws: new Map<string, DefectGroup>(),
      };
      if (includeStats) {
        group.stats = { 
          count: 0, 
          totalArea: 0, 
          maxLongSide: 0, 
          minLongSide: Number.POSITIVE_INFINITY, 
          maxShortSide: 0, 
          minShortSide: Number.POSITIVE_INFINITY, 
          maxArea: 0, 
          minArea: Number.POSITIVE_INFINITY 
        };
      }
      grouped.set(coordKey, group);
    }

    // 映射到 DefectDetails
    const flaw: DefectDetails = {
      type: item.type,
      area: item.area,
      longSide: item.longSide,
      shortSide: item.shortSide,
      score: item.score,
    };

    // 按 type 分组
    let defectGroup = group.flaws.get(item.type);
    if (!defectGroup) {
      defectGroup = { 
        details: [], 
        stats: includeStats ? { 
          count: 0, 
          totalArea: 0, 
          maxLongSide: 0, 
          minLongSide: Number.POSITIVE_INFINITY, 
          maxShortSide: 0, 
          minShortSide: Number.POSITIVE_INFINITY, 
          maxArea: 0, 
          minArea: Number.POSITIVE_INFINITY 
        } : { count: 0, totalArea: 0, maxLongSide: 0, minLongSide: 0, maxShortSide: 0, minShortSide: 0, maxArea: 0, minArea: 0 }
      };
      group.flaws.set(item.type, defectGroup);
    }
    defectGroup.details.push(flaw);

    // 更新统计信息（如果启用）
    if (includeStats && group.stats && defectGroup.stats) {
      // 更新总体统计
      group.stats.count += 1;
      Object.keys(statsConfig).forEach(key => {
        group.stats![key] = statsConfig[key](item, group.stats![key]);
      });

      // 更新按类型统计
      defectGroup.stats.count += 1;
      Object.keys(statsConfig).forEach(key => {
        defectGroup!.stats[key] = statsConfig[key](item, defectGroup!.stats[key]);
      });
    }
  });

  return new ProcessedData(Array.from(grouped.values()));
}